package com.dp.mallchat.common.user.service.impl;

import com.dp.mallchat.common.user.dao.UserDao;
import com.dp.mallchat.common.user.domain.user.entity.User;
import com.dp.mallchat.common.user.service.UserService;
import com.dp.mallchat.common.user.service.WXMsgService;
import com.dp.mallchat.common.user.service.WebSocketService;
import com.dp.mallchat.common.user.service.adapter.TextBuilder;
import com.dp.mallchat.common.user.service.adapter.UserAdapter;
import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.net.URLEncoder;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: dupeng
 * @CreateTime: 2024-05-22  20:29
 * @Description: TODO
 */
@Service
public class WxMsgServiceImpl implements WXMsgService {

    //待认证用户
    private static final ConcurrentHashMap<String, Integer> WITH_AUTHORIZATION_MAP = new ConcurrentHashMap<>();

    //微信网页授权链接
    private static final String URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_userinfo#wechat_redirect";

    @Value("${mallchat.wx.callback}")
    private String callback;

    @Autowired
    private UserDao userDao;
    @Autowired
    @Lazy
    private WebSocketService webSocketService;
    @Autowired
    private UserService userService;


    /**
     * 扫码事件
     *
     * @param wxMpXmlMessage 微信扫码回传对象
     * @param wxMpService    微信服务Service
     * @return
     */
    @Override
    public WxMpXmlOutMessage scan(WxMpXmlMessage wxMpXmlMessage, WxMpService wxMpService) {
        Integer code = Integer.parseInt(getEventKey(wxMpXmlMessage));
        String openId = wxMpXmlMessage.getFromUser();
        User user = userDao.getUserByOpenId(openId);
        //1、用户是否已经注册并且授权
        if (Objects.nonNull(user) && StringUtils.isNotBlank(user.getAvatar())) {
            //走登录成功逻辑，通过code找到channel推送消息
            webSocketService.scanLoginSuccess(code, user.getId());
            return sendRemark(wxMpXmlMessage);
        }

        //2、用户为空，先注册，保存uId, openId
        if (Objects.isNull(user)) {
            User registerUser = User.builder().openId(openId).build();
            userService.register(registerUser);
        }

        //3、扫码成功，等待用户授权
        webSocketService.waitAuthorization(code);

        //4、保存用户openId 与 授权code
        WITH_AUTHORIZATION_MAP.put(openId, code);

        //5、推送授权链接
        return sendAuthorizationLink(wxMpXmlMessage, wxMpService);

    }

    /**
     * 用户授权
     *
     * @param userInfo
     */
    @Override
    public void authorization(WxOAuth2UserInfo userInfo) {
        User user = userDao.getUserByOpenId(userInfo.getOpenid());
        //用户名称为空，标识扫码后未进行授权，需更新用户信息
        if (StringUtils.isBlank(user.getName())) {
            fillUserInfo(user.getId(), userInfo);
        }
        //删除待认证用户
        Integer code = WITH_AUTHORIZATION_MAP.remove(userInfo.getOpenid());
        if (Objects.isNull(code)) {
            return;
        }
        //登录
        webSocketService.scanLoginSuccess(code, user.getId());
    }

    /**
     * 更新用户信息
     *
     * @param uid
     * @param userInfo
     */
    private void fillUserInfo(Long uid, WxOAuth2UserInfo userInfo) {
        User user = UserAdapter.buildUser(uid, userInfo);
        userDao.updateUserInfo(user);
    }


    /**
     * 推送授权链接
     *
     * @param wxMpXmlMessage
     * @param wxMpService
     * @return
     */
    private WxMpXmlOutMessage sendAuthorizationLink(WxMpXmlMessage wxMpXmlMessage, WxMpService wxMpService) {
        String skipUrl = String.format(URL, wxMpService.getWxMpConfigStorage().getAppId(), URLEncoder.encode(callback + "/wx/portal/public/callBack"));
        return TextBuilder.build("请点击链接授权：<a href=\"" + skipUrl + "\">登录</a>", wxMpXmlMessage);
    }

    /**
     * 推送已授权用户说明信息
     * @param wxMpXmlMessage
     * @return
     */
    private WxMpXmlOutMessage sendRemark(WxMpXmlMessage wxMpXmlMessage) {
        return TextBuilder.build("欢迎使用MallChat，请先选择一个频道进行聊天", wxMpXmlMessage);
    }

    private String getEventKey(WxMpXmlMessage wxMpXmlMessage) {
        //扫码关注的渠道事件有前缀，需要去除
        return wxMpXmlMessage.getEventKey().replace("qrscene_", "");
    }
}
